home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -serious- / misc / mmulib / c_sources / mufastrom.c < prev    next >
C/C++ Source or Header  |  1999-11-29  |  22KB  |  527 lines

  1. /*****************************************************************
  2.  ** MuFastRom                                                   **
  3.  **                                                             **
  4.  ** A MMU-Library compatible ROM remapper                       **
  5.  ** Version 1.07 21.08.1999 © THOR-Software, by Thomas Richter  **
  6.  *****************************************************************/
  7.  
  8. /// Includes
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11. #include <exec/ports.h>
  12. #include <dos/dos.h>
  13. #include <mmu/mmubase.h>
  14. #include <mmu/context.h>
  15. #include <mmu/mmutags.h>
  16. #include <workbench/startup.h>
  17.  
  18. #include <proto/exec.h>
  19. #include <proto/mmu.h>
  20. #include <proto/dos.h>
  21. #include <proto/icon.h>
  22. #include <string.h>
  23. ///
  24. /// Defines
  25. #define STRINGDATE "21.8.99"
  26. #define STRINGVERSION "40.7"
  27. #define ROMEND 0x01000000L
  28. #define MAGIC_ROMEND 0x14L
  29. #define CACHEFLAGS (MAPP_CACHEINHIBIT|MAPP_COPYBACK|MAPP_NONSERIALIZED|MAPP_IMPRECISE)
  30. #define TEMPLATE "ON=FASTROM/S,OFF=NOFASTROM/S,HEAD/S,PROTECT/S,NOPROTECT/S"
  31.  
  32. #define OPT_ON  0
  33. #define OPT_OFF 1
  34. #define OPT_HEAD 2
  35. #define OPT_PROTECT 3
  36. #define OPT_NOPROTECT 4
  37. #define OPT_WINDOW 5
  38. #define OPT_COUNT 6
  39. ///
  40. /// Statics
  41. struct MMUBase *MMUBase;
  42. struct DosLibrary *DOSBase;
  43. struct ExecBase *SysBase;
  44. struct Library *IconBase;
  45. ///
  46. /// Protos
  47. int __asm __saveds main(void);
  48. int BuildFastRom(LONG head,LONG protect,LONG noprotect);
  49. int RemoveFastRom(void);
  50. int MapToRom(struct MMUContext *ctx,ULONG source,ULONG mem,ULONG size);
  51. int RemapToRam(struct MMUContext *ctx,ULONG source,ULONG pmem,ULONG mem,ULONG size,LONG protect,LONG noprotect,ULONG cacheflags);
  52. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp);
  53. ///
  54. /// Strukturen
  55. struct FastRomPort {
  56.         struct MsgPort          frp_Port;
  57.         UBYTE                   frp_NoProtect;
  58.         UBYTE                   frp_Protect;
  59.         void                   *frp_Logical;            /* Logical address of the remapped ROM */
  60.         void                   *frp_Physical;           /* Physical location of the RAM used for remapping */
  61.         void                   *frp_RomStart;
  62.         ULONG                   frp_Size;               /* size of the allocated memory */
  63.         struct Library         *frp_Base;               /* Keep the library open */
  64.         ULONG                   frp_CacheFlags;         /* keeps the cache mode of the remapped ROM */
  65.         char                    frp_Name[32];           /* keeps the name of the port */
  66. };
  67. ///
  68.  
  69. char version[]="$VER: MuFastRom " STRINGVERSION " (" STRINGDATE ") © THOR";
  70.  
  71. /// main
  72. int __asm __saveds main(void)
  73. {
  74. LONG args[OPT_COUNT];
  75. struct RDArgs *rd,*myrd;
  76. struct Process *proc;
  77. int rc=20;
  78. LONG err;
  79. struct WBStartup *msg;
  80. BPTR oldout;
  81. struct MsgPort *oldconsole;
  82.  
  83.  
  84.  
  85.         SysBase=*((struct ExecBase **)(4L));
  86.  
  87.         memset(args,0,sizeof(LONG)*OPT_COUNT);
  88.         /* Wait for the workbench startup, if any */
  89.         proc=(struct Process *)FindTask(NULL);
  90.  
  91.         if (!(proc->pr_CLI)) {
  92.                 WaitPort(&(proc->pr_MsgPort));
  93.                 msg=(struct WBStartup *)GetMsg(&(proc->pr_MsgPort));
  94.         } else  msg=NULL;
  95.  
  96.         if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) {
  97.                 if (MMUBase=(struct MMUBase *)OpenLibrary("mmu.library",0L)) {
  98.  
  99.                         err=ERROR_REQUIRED_ARG_MISSING;
  100.  
  101.                         myrd=NULL;      /* reset the temporary ReadArgs */
  102.                         oldout=NULL;
  103.                         oldconsole=NULL;
  104.                         if (msg) {
  105.                                 oldout=SelectOutput(NULL);
  106.                                 oldconsole=SetConsoleTask(NULL);
  107.                                 rd=ReadTTArgs(msg,args,&myrd);
  108.                         } else  rd=ReadArgs(TEMPLATE,args,NULL);
  109.  
  110.                         if (rd) {
  111.                                 if (!GetMMUType()) {
  112.                                         Printf("MuFastRom requires a working MMU.\n");
  113.                                         err=10;
  114.                                 } else {
  115.                                         /* Argument parser worked, call main routine */
  116.                                         if ((args[OPT_ON]) || (!args[OPT_OFF])) /* ON is the default if OFF is not given */
  117.                                                 err=BuildFastRom(args[OPT_HEAD],args[OPT_PROTECT],args[OPT_NOPROTECT]);
  118.  
  119.                                         if (args[OPT_OFF])
  120.                                                 err=RemoveFastRom();
  121.                                 }
  122.  
  123.                                 FreeArgs(rd);
  124.                                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  125.                                 if (msg)  Close(SelectOutput(NULL));
  126.                         } else  err=IoErr();
  127.  
  128.                         if (msg) {
  129.                                 SelectOutput(oldout);
  130.                                 SetConsoleTask(oldconsole);
  131.                         }
  132.  
  133.                         if (err<64) {
  134.                                 rc=err;
  135.                                 err=0;
  136.                         } else {
  137.                                 if (!msg) PrintFault(err,"MuFastRom failed");
  138.                                 rc=10;
  139.                         }
  140.                         SetIoErr(err);
  141.  
  142.                         CloseLibrary((struct Library *)MMUBase);
  143.                 } else PrintFault(ERROR_OBJECT_NOT_FOUND,"MuFastRom requires the mmu.library");
  144.                 CloseLibrary((struct Library *)DOSBase);
  145.         }
  146.  
  147.         return rc;
  148. }
  149. ///
  150. /// ReadTTArgs
  151. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp)
  152. {
  153. struct WBArg *wbarg;
  154. struct DiskObject *dop;
  155. char **tt;                      /* ToolTypes array */
  156. char *wbstr;                    /* Our self-made workbench argument string */
  157. char *here;
  158. BPTR oldlock;
  159. ULONG len;
  160. struct RDArgs *rd=NULL,*myrd=NULL;
  161. LONG err=0;
  162. BPTR newout;
  163.  
  164.         if (IconBase=OpenLibrary("icon.library",37L)) {
  165.                 if (wbarg=msg->sm_ArgList) {
  166.                         /* use a project icon if there is one... */
  167.                         if (msg->sm_NumArgs > 1) wbarg++;
  168.  
  169.                         /* go into the directory */
  170.                         oldlock=CurrentDir(wbarg->wa_Lock);
  171.  
  172.                         if (dop=GetDiskObject(wbarg->wa_Name)) {
  173.                                 if (tt=dop->do_ToolTypes) {
  174.                                         /* Read a special tool type for the output window */
  175.  
  176.                                         /* Calc the size of the argument string */
  177.  
  178.                                         len = 3;        /* reserve space for SPC,LF,NUL */
  179.                                         while (*tt) {
  180.                                                 len += strlen(*tt)+1;   /* string, plus space */
  181.                                                 tt++;
  182.                                         }
  183.  
  184.                                         if (wbstr=AllocVec(len,MEMF_PUBLIC)) {
  185.                                                 /* Now copy the arguments into this string, one by one
  186.                                                    and check whether the argument string is still valid. */
  187.  
  188.                                                 tt=dop->do_ToolTypes;
  189.                                                 here=wbstr;
  190.                                                 do{
  191.                                                         *here='\0';                     /* terminate string */
  192.                                                         /* Check whether this tool type is
  193.                                                            commented out. Just ignore it in this case */
  194.                                                         if (*tt) {
  195.                                                                 if (**tt=='(' || **tt==';')
  196.                                                                         continue;
  197.  
  198.                                                                 strcpy(here,*tt);      /* Add TT string */
  199.                                                         }
  200.                                                         len=strlen(here);
  201.                                                         here[len]='\n';
  202.                                                         here[len+1]='\0';               /* terminate string */
  203.  
  204.                                                         /* Now try to ReadArg' this string */
  205.  
  206.                                                         /* release old arguments left over from last loop */
  207.                                                         if (rd) FreeArgs(rd);
  208.                                                         if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  209.                                                         rd=NULL;
  210.                                                         memset(args,0,sizeof(LONG)*OPT_COUNT);
  211.  
  212.                                                         if (myrd=AllocDosObject(DOS_RDARGS,NULL)) {
  213.                                                                 /* Allocate and setup the ReadArgs source */
  214.                                                                 myrd->RDA_Source.CS_Buffer=wbstr;
  215.                                                                 myrd->RDA_Source.CS_Length=strlen(wbstr);
  216.  
  217.                                                                 if (rd=ReadArgs(TEMPLATE ",WINDOW/K",args,myrd)) {
  218.                                                                         /* Is this still valid? */
  219.                                                                         here[len]=' ';
  220.                                                                         here+=len+1;
  221.                                                                         /* if so, accept this argument and go on */
  222.                                                                 } else {
  223.                                                                         err=IoErr();
  224.                                                                         if (err==ERROR_NO_FREE_STORE) break;
  225.                                                                         else    err=0;  /* Ignore unknown or invalid arguments silently */
  226.                                                                 }
  227.                                                         } else {
  228.                                                                 err=ERROR_NO_FREE_STORE;
  229.                                                                 break;
  230.                                                         }
  231.                                                 }while(*tt++);
  232.  
  233.                                                 FreeVec(wbstr);
  234.                                         } else err=ERROR_NO_FREE_STORE;
  235.                                 } else err=ERROR_REQUIRED_ARG_MISSING; /* Huh, how should this happen ? */
  236.                                 FreeDiskObject(dop);
  237.                         } else err=IoErr();
  238.                         CurrentDir(oldlock);
  239.                 } else err=ERROR_REQUIRED_ARG_MISSING; /* This should not happen either */
  240.                 CloseLibrary(IconBase);
  241.         } else err=ERROR_OBJECT_NOT_FOUND;    /* This should not happen */
  242.  
  243.         /* Open an output stream */
  244.  
  245.         if (err==0) {
  246.                 if (newout=Open((args[OPT_WINDOW])?((char *)args[OPT_WINDOW]):("NIL:"),MODE_NEWFILE)) {
  247.                         SelectOutput(newout);
  248.                         /* Hack in the output console. Well, well... */
  249.                         SetConsoleTask(((struct FileHandle *)(BADDR(newout)))->fh_Type);
  250.                 } else err=IoErr();
  251.         }
  252.  
  253.         if (err) {
  254.                 if (rd)   FreeArgs(rd);
  255.                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  256.                 SetIoErr(err);
  257.                 rd=NULL;
  258.                 myrd=NULL;
  259.         }
  260.  
  261.         *tmp=myrd;
  262.         return rd;
  263. }
  264. ///
  265. /// BuildFastRom
  266. int BuildFastRom(LONG head,LONG protect,LONG noprotect)
  267. {
  268. void *mem,*source,*pmem;
  269. ULONG size,psize;
  270. ULONG props;
  271. struct FastRomPort *port;
  272. struct MMUContext *ctx,*sctx;   /* default context, supervisorcontext */
  273. int err=ERROR_NO_FREE_STORE;
  274.  
  275.  
  276.         Forbid();                               /* Shut up PatchWork */
  277.  
  278.         /* If this is already installed, warn and return. */
  279.  
  280.         if (FindPort("« MuFastRom »")) {
  281.                 Permit();
  282.                 Printf("MuFastRom already running.\n");
  283.                 return 5;
  284.         }
  285.  
  286.         Permit();
  287.  
  288.         ctx=DefaultContext();   /* get the default context */
  289.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  290.  
  291.         /* Read the size of the ROM */
  292.         size=*((ULONG *)(ROMEND-MAGIC_ROMEND));
  293.  
  294.         /* The start of the ROM */
  295.         source=((UBYTE *)ROMEND)-size;
  296.  
  297.         props=GetProperties(sctx,(ULONG)source,TAG_DONE);
  298.         props|=GetProperties(ctx,(ULONG)source,TAG_DONE);
  299.  
  300.         if (props & MAPP_REMAPPED) {
  301.                 Printf("The ROM is already remapped to RAM.\n");
  302.                 return 5;
  303.         }
  304.  
  305.  
  306.         /* now allocate the memory for the ROM image. To keep the
  307.            MMU tables as effective as possible, we try to align
  308.            this */
  309.  
  310.         /* We request FAST here, explicitly. Taking chip memory for the
  311.            ROM image doesn't make sense, this isn't fast either... */
  312.  
  313.         mem=AllocAligned(size,(head)?(MEMF_PUBLIC|MEMF_FAST):(MEMF_REVERSE|MEMF_PUBLIC|MEMF_FAST),RemapSize(ctx));
  314.         if (mem) {
  315.  
  316.                 pmem=mem;
  317.                 psize=size;
  318.                 PhysicalLocation(ctx,&pmem,&psize);
  319.                 if (psize!=size) {
  320.                         Printf("The destination memory is fragmentated, unsupported.\n");
  321.                 } else {
  322.  
  323.                  /* Read the cache flags */
  324.                  props=GetProperties(ctx,(ULONG)mem,TAG_DONE) & CACHEFLAGS;
  325.  
  326.                  /* Copy the ROM */
  327.                  CopyMemQuick(source,mem,size);
  328.  
  329.                  /* Write it out, really */
  330.                  CacheClearU();
  331.  
  332.                  port=AllocMem(sizeof(struct FastRomPort),MEMF_PUBLIC|MEMF_CLEAR);
  333.                  if (port) {
  334.                         if (!RemapToRam(ctx,(ULONG)source,(ULONG)pmem,(ULONG)mem,size,protect,noprotect,props)) {
  335.                                 if (!RemapToRam(sctx,(ULONG)source,(ULONG)pmem,(ULONG)mem,size,protect,noprotect,props)) {
  336.  
  337.                                         /* we're done now */
  338.                                         port->frp_Port.mp_Node.ln_Type=NT_MSGPORT;
  339.                                         port->frp_Port.mp_Node.ln_Name=port->frp_Name;
  340.                                         strcpy(port->frp_Name,"« MuFastRom »");
  341.                                         port->frp_Port.mp_Flags=PA_IGNORE;
  342.                                         NewList(&(port->frp_Port.mp_MsgList));
  343.  
  344.                                         port->frp_RomStart=source;
  345.                                         port->frp_Physical=pmem;
  346.                                         port->frp_Logical=mem;
  347.                                         port->frp_Size=size;
  348.                                         port->frp_NoProtect=noprotect;
  349.                                         port->frp_Protect=protect;
  350.                                         port->frp_CacheFlags=props;
  351.                                         port->frp_Base=OpenLibrary("mmu.library",0L);
  352.                                         AddPort(&(port->frp_Port));
  353.  
  354.                                         /* Do not release the memory or the port */
  355.                                         mem=NULL;
  356.                                         port=NULL;
  357.  
  358.                                         err=0;
  359.                                 } else {
  360.                                         /* The first call failed. Let's see if we can
  361.                                            undo the first modification */
  362.                                         if (MapToRom(ctx,(ULONG)source,(ULONG)mem,size)) {
  363.                                                 err=32;
  364.                                                 Printf("Failed to build FastROM, failed to restore old properties.");
  365.                                                 /* We can't release the memory here, simply because
  366.                                                    it is still in use. Urghl. */
  367.                                                 mem=NULL;
  368.                                         }
  369.                                 }
  370.                         }
  371.                         if (port) FreeMem(port,sizeof(struct FastRomPort));
  372.                  }
  373.                 }
  374.                 if (mem) FreeMem(mem,size);
  375.         }
  376.  
  377.         return err;
  378. }
  379. ///
  380. /// RemoveFastRom
  381. int RemoveFastRom(void)
  382. {
  383. struct MMUContext *ctx,*sctx;
  384. struct FastRomPort *port;
  385. ULONG size,props;
  386. void *mem,*pmem,*source;
  387. int err=ERROR_NO_FREE_STORE;
  388.  
  389.  
  390.         Forbid();                               /* Shut up PatchWork */
  391.  
  392.         /* If this is not installed, warn and return. */
  393.  
  394.         port=(struct FastRomPort *)FindPort("« MuFastRom »");
  395.  
  396.         if (port==NULL) {
  397.                 Permit();
  398.                 Printf("MuFastRom not installed.\n");
  399.                 return 5;
  400.         }
  401.         /* Remove it, to ensure nobody else tries to remove it */
  402.         RemPort(&(port->frp_Port));
  403.         Permit();
  404.  
  405.         ctx=DefaultContext();   /* get the default context */
  406.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  407.  
  408.         size=port->frp_Size;
  409.         pmem=port->frp_Physical;
  410.         mem=port->frp_Logical;
  411.         source=port->frp_RomStart;
  412.         props=port->frp_CacheFlags;
  413.  
  414.         /* Remove the properties right here... */
  415.  
  416.         if (!MapToRom(ctx,(ULONG)source,(ULONG)mem,size)) {
  417.                 if (!MapToRom(sctx,(ULONG)source,(ULONG)mem,size)) {
  418.                         FreeMem(mem,size);
  419.  
  420.                         /* Close the mmu.lib so it can be flushed... */
  421.  
  422.                         if (port->frp_Base)
  423.                                 CloseLibrary(port->frp_Base);
  424.  
  425.                         FreeMem(port,sizeof(struct FastRomPort));
  426.                         err=0;
  427.                 } else {
  428.                         /* Failed. We should try to restore the settings */
  429.                         RemapToRam(ctx,(ULONG)source,(ULONG)pmem,(ULONG)mem,size,(LONG)(port->frp_Protect),(LONG)(port->frp_NoProtect),props);
  430.                         /* In case this doesn't work, tough luck. */
  431.                 }
  432.         }
  433.  
  434.         if (err) {
  435.                 /* Better luck next time... */
  436.                 AddPort(&(port->frp_Port));
  437.                 Printf("Can't remove the FastRom node, sorry.\n");
  438.         }
  439.  
  440.         return err;
  441. }
  442. ///
  443. /// RemapToRam
  444. int RemapToRam(struct MMUContext *ctx,ULONG source,ULONG pmem,ULONG mem,ULONG size,LONG protect,LONG noprotect,ULONG cacheflags)
  445. {
  446. struct MinList *ctxl;
  447. ULONG oldprops;
  448. ULONG rommask,mirrormask;
  449.  
  450.         if (ctxl=GetMapping(ctx)) {
  451.          /* get the properties of the ROM */
  452.          oldprops=GetProperties(ctx,source,TAG_DONE);
  453.  
  454.          oldprops |= MAPP_REMAPPED;
  455.          rommask=MAPP_REMAPPED|MAPP_COPYBACK;   /* Define these bits for the ROM image */
  456.          mirrormask=0;                          /* ...and these for the RAM mirror */
  457.  
  458.          /* Protection enabled? */
  459.          if (protect) {
  460.                 /* active or passive protection? */
  461.                 if (oldprops & MAPP_WRITEPROTECTED) {
  462.                         /* here aggressive, enable protection
  463.                            and allow MuForce to repair access faults */
  464.                         rommask |= MAPP_WRITEPROTECTED|MAPP_REPAIRABLE;
  465.                         mirrormask |= MAPP_WRITEPROTECTED|MAPP_REPAIRABLE;
  466.                 } else {
  467.                         rommask |= MAPP_ROM;
  468.                         mirrormask |= MAPP_ROM;
  469.                         oldprops |= MAPP_ROM;
  470.                 }
  471.          } else if (noprotect) {
  472.                 /* disable all kinds of protection */
  473.                 oldprops &= ~(MAPP_ROM|MAPP_WRITEPROTECTED);
  474.                 rommask |= MAPP_ROM | MAPP_WRITEPROTECTED;
  475.                 mirrormask |= MAPP_ROM | MAPP_WRITEPROTECTED;
  476.          }
  477.  
  478.          /* Enter caching mode */
  479.          oldprops &= ~CACHEFLAGS;
  480.          oldprops |= cacheflags;
  481.          rommask |= CACHEFLAGS;
  482.  
  483.          if (SetProperties(ctx,oldprops,rommask,source,size,MAPTAG_DESTINATION,pmem,TAG_DONE)) {
  484.           if (SetProperties(ctx,oldprops,mirrormask,mem,size,TAG_DONE)) {
  485.            if (RebuildTree(ctx)) {
  486.                   ReleaseMapping(ctx,ctxl);
  487.                   return 0;     /* Everything worked fine */
  488.            } /* the MMU tree could not be build. It is unmodified in this case */
  489.           }
  490.          } /* the modifications could not be made */
  491.          /* Re-install the old properties. This can't fail. */
  492.          SetPropertyList(ctx,ctxl);
  493.          ReleaseMapping(ctx,ctxl);
  494.         }
  495.  
  496.         return ERROR_NO_FREE_STORE;
  497. }
  498. ///
  499. /// MapToRom
  500. int MapToRom(struct MMUContext *ctx,ULONG source,ULONG mem,ULONG size)
  501. {
  502. struct MinList *ctxl;
  503.  
  504.         if (ctxl=GetMapping(ctx)) {
  505.          if (SetProperties(ctx,0,MAPP_REMAPPED|CACHEFLAGS,source,size,TAG_DONE)) {
  506.           if (SetProperties(ctx,0,MAPP_ROM|MAPP_WRITEPROTECTED|MAPP_REPAIRABLE,mem,size,TAG_DONE)) {
  507.            if (RebuildTree(ctx)) {
  508.                   ReleaseMapping(ctx,ctxl);
  509.                   return 0;     /* Everything worked fine */
  510.            } /* the MMU tree could not be build. It is unmodified in this case */
  511.           }
  512.          } /* the modifications could not be made */
  513.          /* Re-install the old properties. This can't fail. */
  514.          SetPropertyList(ctx,ctxl);
  515.          ReleaseMapping(ctx,ctxl);
  516.         }
  517.  
  518.         return ERROR_NO_FREE_STORE;
  519. }
  520. ///
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.